home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 235 / Issue 235 - September 2007 - DPCS0907DVD.ISO / Microsoft / Expression Blend / Blend.en.msi / Sparkle.GPiano.Window1.xaml.cs.en < prev    next >
Encoding:
Text File  |  2007-03-19  |  37.5 KB  |  592 lines

  1.  ■using System;
  2. using System.IO;
  3. using System.Net;
  4. using System.Windows;
  5. using System.Windows.Controls;
  6. using System.Windows.Data;
  7. using System.Windows.Media;
  8. using System.Windows.Media.Animation;
  9. using System.Windows.Navigation;
  10. using System.Windows.Input;
  11. using System.Collections.Generic;
  12. using System.Diagnostics;
  13. using System.Timers;
  14. using Microsoft.Win32;
  15. using System.Collections.ObjectModel;
  16. namespace GrandPiano
  17. {
  18.     public partial class Window1
  19.     {
  20.         // Current note played.
  21.         String note = "";
  22.         // While a note is pressed value = true.
  23.         Boolean isKeyPressed = false;
  24.         
  25.         // Holds names of the notes to be used in a foreach loop.
  26.         List<string> notesCache = new List<string>();
  27.         // Song that is saved and loaded.
  28.         List<Keyframe> song = new List<Keyframe>();
  29.         // Recording and Playback flags.
  30.         Boolean isRecording = false;
  31.         Boolean isPlaying = false;
  32.         
  33.         // Time references for playback.
  34.         TimeSpan currentTime;
  35.         TimeSpan totalTime;
  36.         
  37.         // Keeps track of the next note that will play to synchronize with Fast Forward and Rewind.
  38.         Keyframe nextNoteToPlay;
  39.         int indexNextNote;
  40.         // Timer that controls Recording and Playback.
  41.         Timer tick = new Timer();
  42.         int min = 0;
  43.         int sec = 0;
  44.         int dec = 0;
  45.         #region Initialization
  46.         public Window1()
  47.         {
  48.             this.InitializeComponent();
  49.         }
  50.         /// <summary>
  51.         /// This method makes sure that all the elements are already loaded and ready,
  52.         /// then it plays all the audio files to make sure they are cached in memory and improve performance.
  53.         /// </summary>
  54.         protected override void OnInitialized(EventArgs e)
  55.         {
  56.             base.OnInitialized(e);
  57.             CacheAudioFiles();
  58.         }
  59.         /// <summary>
  60.         /// Plays all audio files to improve performance when they play for the first time.
  61.         /// Notes as C_7 indicates C# (D_7 is D#).
  62.         /// </summary>
  63.         private void CacheAudioFiles()
  64.         {
  65.             notesCache.Add("C7");
  66.             notesCache.Add("C_7");
  67.             notesCache.Add("D7");
  68.             notesCache.Add("D_7");
  69.             notesCache.Add("E7");
  70.             notesCache.Add("F7");
  71.             notesCache.Add("F_7");
  72.             notesCache.Add("G7");
  73.             notesCache.Add("G_7");
  74.             notesCache.Add("A7");
  75.             notesCache.Add("A_7");
  76.             notesCache.Add("B7");
  77.             ChangeNotesMute(true);
  78.             foreach (string n in notesCache)
  79.             {
  80.                 FrameworkElement audioKey = (FrameworkElement)keys.FindName(n);
  81.                 Storyboard s = (Storyboard)audioKey.FindResource(n + "_wma");
  82.                 s.Begin(audioKey);
  83.             }
  84.         }
  85.         private void ChangeNotesMute(bool mute)
  86.         {
  87.             foreach (string n in notesCache)
  88.             {
  89.                 MediaElement m = (MediaElement)audio.FindName(n + "_wma");
  90.                 m.IsMuted = mute;
  91.             }
  92.         }
  93.         #endregion
  94.         #region File Management
  95.         private void OnLoadSong(object sender, RoutedEventArgs e)
  96.         {
  97.             OnOpenFile();
  98.         }
  99.         private void OnSaveSong(object sender, RoutedEventArgs e)
  100.         {
  101.             if (song.Count > 0)
  102.             {
  103.                 OnSaveFile();
  104.             }
  105.             else
  106.             {
  107.                 MessageBox.Show("There is no song to save.");
  108.             }
  109.         }
  110.         private void OnExit(object sender, RoutedEventArgs e)
  111.         {
  112.             this.Close();
  113.         }
  114.         /// <summary>
  115.         /// Saves the song in a binary file.
  116.         /// Because TimeSpan can't be saved directly, it is converted to String.
  117.         /// </summary>
  118.         public void Save(string fileName)
  119.         {
  120.             if (File.Exists(fileName))
  121.             {
  122.                 MessageBox.Show("{0} already exists!", fileName);
  123.                 return;
  124.             }
  125.             FileStream fs = new FileStream(fileName, FileMode.CreateNew);
  126.             BinaryWriter w = new BinaryWriter(fs);
  127.             foreach (Keyframe k in this.song)
  128.             {
  129.                 String time = k.Time.ToString();
  130.                 w.Write(time);
  131.                 String note = k.Note;
  132.                 w.Write(note);
  133.             }
  134.             w.Close();
  135.             fs.Close();
  136.         }
  137.         /// <summary>
  138.         /// Loaded the binary file, converting time from String back to TimeSpan.
  139.         /// </summary>
  140.         public void Load(String fileName)
  141.         {
  142.             FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
  143.             BinaryReader r = new BinaryReader(fs);
  144.             song = new List<Keyframe>();
  145.             while (fs.Position < fs.Length)
  146.             {
  147.                 String t = r.ReadString();
  148.                 String[] splitMin = t.Split(':');
  149.                 int min = Convert.ToInt32(splitMin[1]);
  150.                 String[] splitSecDec = splitMin[2].Split('.');
  151.                 int sec = Convert.ToInt32(splitSecDec[0]);
  152.                 int dec;
  153.                 if (splitSecDec.Length > 1)
  154.                 {
  155.                     dec = Convert.ToInt32(splitSecDec[1]);
  156.                 }
  157.                 else
  158.                 {
  159.                     dec = 0;
  160.                 }
  161.                 dec /= 100000;
  162.                 TimeSpan time = new TimeSpan(0, 0, min, sec, (dec * 10));
  163.                 String note = r.ReadString();
  164.                 Keyframe k = new Keyframe(time, note);
  165.                 song.Add(k);
  166.             }
  167.             r.Close();
  168.             fs.Close();
  169.         }
  170.         void OnOpenFile()
  171.         {
  172.             OpenFileDialog fileDialog = new OpenFileDialog();
  173.             fileDialog.Title = "Open Song";
  174.             fileDialog.RestoreDirectory = true;
  175.             fileDialog.InitialDirectory = System.IO.Directory.GetCurrentDirectory();
  176.             fileDialog.Filter = "Grand Piano Songs (*.gps)|*.gps";
  177.             bool? dialogResult = fileDialog.ShowDialog(this);
  178.             if (dialogResult.HasValue && dialogResult.Value)
  179.             {
  180.                 try
  181.                 {
  182.                     this.Load(fileDialog.FileName);
  183.                 }
  184.                 catch (Exception exception)
  185.                 {
  186.                     string error = String.Format("Cannot open file '{0}'.\n{1}", fileDialog.FileName, exception.Message);
  187.                     MessageBox.Show(this, error, "Cannot open file", MessageBoxButton.OK, MessageBoxImage.Error);
  188.                 }
  189.             }
  190.         }
  191.         void OnSaveFile()
  192.         {
  193.             SaveFileDialog fileDialog = new SaveFileDialog();
  194.             fileDialog.Title = "Save Song As";
  195.             fileDialog.RestoreDirectory = true;
  196.             fileDialog.InitialDirectory = System.IO.Directory.GetCurrentDirectory();
  197.             fileDialog.Filter = "Grand Piano Songs (*.gps)|*.gps";
  198.             bool? dialogResult = fileDialog.ShowDialog(this);
  199.             if (dialogResult.HasValue && dialogResult.Value)
  200.             {
  201.                 try
  202.                 {
  203.                     this.Save(fileDialog.FileName);
  204.                 }
  205.                 catch (Exception exception)
  206.                 {
  207.                     string error = String.Format("Cannot save file '{0}'.\n{1}", fileDialog.FileName, exception.Message);
  208.                     MessageBox.Show(this, error, "Cannot save file", MessageBoxButton.OK, MessageBoxImage.Error);
  209.                 }
  210.             }
  211.         }
  212.         #endregion
  213.         #region Key Events
  214.         protected override void OnTextInput(TextCompositionEventArgs e)
  215.         {
  216.             if ((string.IsNullOrEmpty(this.note)) && (!isPlaying))
  217.             {
  218.                 HideKeyImage();
  219.                 note = "";
  220.                 switch (e.Text.ToLower())
  221.                 {
  222.                     case "z":
  223.                         note = "C7";
  224.                         break;
  225.                     case "s":
  226.                         note = "C_7";
  227.                         break;
  228.                     case "x":
  229.                         note = "D7";
  230.                         break;
  231.                     case "d":
  232.                         note = "D_7";
  233.                         break;
  234.                     case "c":
  235.                         note = "E7";
  236.                         break;
  237.                     case "v":
  238.                         note = "F7";
  239.                         break;
  240.                     case "g":
  241.                         note = "F_7";
  242.                         break;
  243.                     case "b":
  244.                         note = "G7";
  245.                         break;
  246.                     case "h":
  247.                         note = "G_7";
  248.                         break;
  249.                     case "n":
  250.                         note = "A7";
  251.                         break;
  252.                     case "j":
  253.                         note = "A_7";
  254.                         break;
  255.                     case "m":
  256.                         note = "B7";
  257.                         break;
  258.                     default:
  259.                         break;
  260.                 }
  261.                 PlayNote();
  262.                 if (!string.IsNullOrEmpty(note))
  263.                 {
  264.                     base.OnTextInput(e);
  265.                 }
  266.                 else
  267.                 {
  268.                     e.Handled = true;
  269.                 }
  270.             }
  271.         }
  272.         protected override void OnKeyUp(KeyEventArgs e)
  273.         {
  274.             if (!isPlaying)
  275.             {
  276.                 base.OnKeyUp(e);
  277.                 HideKeyImage();
  278.                 this.note = "";
  279.             }
  280.         }
  281.         #endregion
  282.         #region Mouse Events
  283.         private void OnMouseDown(object sender, MouseButtonEventArgs e)
  284.         {
  285.             if (!isPlaying)
  286.             {
  287.                 FrameworkElement me = sender as FrameworkElement;
  288.                 note = me.Name.ToString();
  289.                 PlayNote();
  290.             }
  291.         }
  292.         private void OnMouseUp(object sender, MouseButtonEventArgs e)
  293.         {
  294.             if (!isPlaying)
  295.             {
  296.                 HideKeyImage();
  297.             }
  298.         }
  299.         #endregion
  300.         #region Piano Keys and Notes
  301.         private void PlayNote()
  302.         {
  303.             // The audio is muted because of cache initialization.
  304.             // The first time they play it is necessary to unmute.
  305.             if (C7_wma.IsMuted) ChangeNotesMute(false);
  306.             if ((note != "") && (!isKeyPressed))
  307.             {
  308.                 isKeyPressed = true;
  309.                 FrameworkElement audioKey = (FrameworkElement)keys.FindName(note);
  310.                 FrameworkElement imgKey = (FrameworkElement)keys.FindName("key" + note);
  311.                 imgKey.Visibility = Visibility.Visible;
  312.                 // Each note is played as simple Storyboard with a MediaTimeline.
  313.                 Storyboard s = (Storyboard)audioKey.FindResource(note + "_wma");
  314.                 s.Begin(audioKey);
  315.                 if (isRecording) SetKeyframe(note);
  316.             }
  317.         }
  318.         private void HideKeyImage()
  319.         {
  320.             if (note != "")
  321.             {
  322.                 FrameworkElement imgKey = (FrameworkElement)keys.FindName("key" + note);
  323.                 imgKey.Visibility = Visibility.Hidden;
  324.                 isKeyPressed = false;
  325.                 note = "";
  326.             }
  327.         }
  328.         #endregion
  329.         #region Playback and Recording
  330.         /// <summary>
  331.         /// Sets a keyframe using the Data Model Keyframe, which holds:
  332.         /// 1. Time the note is played.
  333.         /// 2. Note played.
  334.         /// </summary>
  335.         private void SetKeyframe(String note)
  336.         {
  337.             Keyframe k = new Keyframe(new TimeSpan(0, 0, min, sec, (dec * 10)), note);
  338.             song.Add(k);
  339.         }
  340.         private void OnPlay(object sender, RoutedEventArgs e)
  341.         {
  342.             if (!isRecording)
  343.             {
  344.                 if (song.Count != 0)
  345.                 {
  346.                     if (!isPlaying)
  347.                     {
  348.                         GetTotalTime();
  349.                         min = sec = dec = 0;
  350.                         isPlaying = true;
  351.                         Storyboard rec = (Storyboard)LayoutRoot.FindResource("showPlaying");
  352.                         rec.Begin(LayoutRoot);
  353.                         tick.Elapsed += new ElapsedEventHandler(tick_ElapsedPlay);
  354.                         tick.Interval = 100;
  355.                         tick.Start();
  356.                         // Gets the first note to play
  357.                         if (song.Count > 1)
  358.                         {
  359.                             UpdateCurrentTime();
  360.                             indexNextNote = 0;
  361.                             nextNoteToPlay = song[indexNextNote];
  362.                         }
  363.                     }
  364.                 }
  365.                 else
  366.                 {
  367.                     Storyboard rec = (Storyboard)LayoutRoot.FindResource("showEmpty");
  368.                     rec.Begin(LayoutRoot);
  369.                 }
  370.             }
  371.         }
  372.         private void OnStop(object sender, RoutedEventArgs e)
  373.         {
  374.             if (isRecording)
  375.             {
  376.                 StopRecording();
  377.             }
  378.             else if (isPlaying)
  379.             {
  380.                 isPlaying = false;
  381.                 Storyboard rec = (Storyboard)LayoutRoot.FindResource("hidePlaying");
  382.                 rec.Begin(LayoutRoot);
  383.                 tick.Elapsed -= new ElapsedEventHandler(tick_ElapsedPlay);
  384.                 tick.Stop();
  385.             }
  386.         }
  387.         private void OnRec(object sender, RoutedEventArgs e)
  388.         {
  389.             if (!isPlaying)
  390.             {
  391.                 if (isRecording)
  392.                 {
  393.                     StopRecording();
  394.                 }
  395.                 else
  396.                 {
  397.                     min = sec = dec = 0;
  398.                     song = new List<Keyframe>();
  399.                     isRecording = true;
  400.                     recOn.Visibility = Visibility.Visible;
  401.                     Storyboard rec = (Storyboard)LayoutRoot.FindResource("showRecording");
  402.                     rec.Begin(LayoutRoot);
  403.                     tick.Elapsed += new ElapsedEventHandler(tick_ElapsedRec);
  404.                     tick.Interval = 100;
  405.                     tick.Start();
  406.                 }
  407.             }
  408.         }
  409.         private void StopRecording()
  410.         {
  411.             isRecording = false;
  412.             recOn.Visibility = Visibility.Hidden;
  413.             Storyboard rec = (Storyboard)LayoutRoot.FindResource("hideRecording");
  414.             rec.Begin(LayoutRoot);
  415.             SetKeyframe("END");
  416.             tick.Elapsed -= new ElapsedEventHandler(tick_ElapsedRec);
  417.             tick.Stop();
  418.         }
  419.         /// <summary>
  420.         /// Updates the display of the recording elapsed time.
  421.         /// </summary>
  422.         void tick_ElapsedRec(object sender, ElapsedEventArgs e)
  423.         {
  424.             DelayedCallback.Invoke(TimeSpan.FromSeconds(0), delegate()
  425.             {
  426.                 recTime.Text = GetElapsedTime();
  427.             });
  428.         }
  429.         /// <summary>
  430.         /// Plays notes and updates the display of the playback elapsed time.
  431.         /// </summary>
  432.         void tick_ElapsedPlay(object sender, ElapsedEventArgs e)
  433.         {
  434.             DelayedCallback.Invoke(TimeSpan.FromSeconds(0), delegate()
  435.             {
  436.                 UpdateCurrentTime();
  437.                 if (currentTime != totalTime)
  438.                 {
  439.                     if (song.Count > 1)
  440.                     {
  441.                         HideKeyImage();
  442.                         if (currentTime == nextNoteToPlay.Time)
  443.                         {
  444.                             note = nextNoteToPlay.Note;
  445.                             isKeyPressed = false;
  446.                             PlayNote();
  447.                             indexNextNote++;
  448.                             nextNoteToPlay = song[indexNextNote];
  449.                         }
  450.                     }
  451.                     playTimeElapsed.Text = GetElapsedTime();
  452.                 }
  453.                 else
  454.                 {
  455.                     HideKeyImage();
  456.                     isPlaying = false;
  457.                     Storyboard rec = (Storyboard)LayoutRoot.FindResource("hidePlaying");
  458.                     rec.Begin(LayoutRoot);
  459.                     tick.Elapsed -= new ElapsedEventHandler(tick_ElapsedPlay);
  460.                     tick.Stop();
  461.                 }
  462.             });
  463.         }
  464.         private void UpdateCurrentTime()
  465.         {
  466.             currentTime = new TimeSpan(0, 0, min, sec, (dec * 10));
  467.         }
  468.         private String GetElapsedTime()
  469.         {
  470.             dec++;
  471.             if (dec == 10)
  472.             {
  473.                 dec = 0;
  474.                 sec++;
  475.             }
  476.             if (sec == 60)
  477.             {
  478.                 sec = 0;
  479.                 min++;
  480.             }
  481.             String secStr = sec.ToString();
  482.             String minStr = min.ToString();
  483.             if (sec < 10) secStr = "0" + secStr;
  484.             if (min < 10) minStr = "0" + minStr;
  485.             return minStr + ":" + secStr + ":" + dec;
  486.         }
  487.         private String GetTotalTime()
  488.         {
  489.             Keyframe lastKey = song[song.Count - 1];
  490.             totalTime = lastKey.Time;
  491.             double ticks = totalTime.Milliseconds / 10;
  492.             double dec = Math.Floor(ticks);
  493.             int sec = totalTime.Seconds;
  494.             int min = totalTime.Minutes;
  495.             String decStr = dec.ToString();
  496.             String secStr = sec.ToString();
  497.             String minStr = min.ToString();
  498.             if (sec < 10) secStr = "0" + secStr;
  499.             if (min < 10) minStr = "0" + minStr;
  500.             return minStr + ":" + secStr + ":" + decStr;
  501.         }
  502.         private void OnForward(object sender, RoutedEventArgs e)
  503.         {
  504.             if (isPlaying)
  505.             {
  506.                 indexNextNote = (indexNextNote + 1 > (song.Count - 1)) ? (song.Count - 1) : indexNextNote + 1;
  507.                 nextNoteToPlay = song[indexNextNote];
  508.                 currentTime = song[indexNextNote].Time;
  509.                 min = currentTime.Minutes;
  510.                 sec = currentTime.Seconds;
  511.                 dec = 0;
  512.             }
  513.         }
  514.         private void OnRewind(object sender, RoutedEventArgs e)
  515.         {
  516.             if (isPlaying)
  517.             {
  518.                 indexNextNote = (indexNextNote - 1 < 0) ? 0 : indexNextNote - 1;
  519.                 nextNoteToPlay = song[indexNextNote];
  520.                 currentTime = song[indexNextNote].Time;
  521.                 min = currentTime.Minutes;
  522.                 sec = currentTime.Seconds;
  523.                 dec = 0;
  524.             }
  525.         }
  526.         #endregion
  527.     }
  528. }